﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.IO;
using System.Xml;

namespace BookInfoExtractor
{
     /// <summary>
     ///    Provides the means to map object to XML and vice versa.
     ///    Uses the System.Runtime.DataContractSerializer for mapping.
     /// </summary>
    public class ObjectXmlMapper:IObjectXmlMapper
    {
        internal const string DATACONTRACTSERIALISER_NAMESPACE_URI = "http://schemas.datacontract.org/2004/07/BookInfoExtractor";

        #region IObjectXmlMapper Members

        /// <summary>
        ///     This method uses the System.Runtime.DataContractSerializer WriteObject 
        ///     to export object to XML.
        /// </summary>
        /// <param name="patternObject"></param>
        /// <returns>Input Object converted to XML format</returns>
        /// <exception cref="ObjectXmlMappingException" />
        public byte[] Export(object patternObject)
        {
            byte[] xmlFile = null;
            DataContractSerializer objDCSerializer = null;
            MemoryStream msOp = null;

            try
            {
                objDCSerializer = new DataContractSerializer(patternObject.GetType());
                msOp = new MemoryStream();
                objDCSerializer.WriteObject(msOp, patternObject);

                xmlFile = msOp.ToArray();

                //Close and Dispose MemoryStream object
                //handle memory leakage problem
                msOp.Close(); 
                msOp.Dispose();
                msOp = null;
                
            }
            catch(InvalidDataContractException invalidDataContractEx)
            {
                throw invalidDataContractEx; 
            }
            catch(SerializationException serialisationEx)
            {
                throw serialisationEx;
            }
            catch(Exception ex)
            {
                throw ex;
            }
            finally
            {
                objDCSerializer = null;
                msOp = null;
                patternObject = null;
            }
            return xmlFile; 
        }

        /// <summary>
        ///     This method uses the System.Runtime.DataContractSerializer ReadObject
        ///     to import object from XML.
        /// </summary>
        /// <param name="xmlFile"></param>
        /// <param name="typeToMap"></param>
        /// <returns>Input XML converted to object</returns>
        /// <exception cref="ObjectXmlMappingException" />
        public object Import(byte[] xmlFile, Type typeToMap)
        {
            DataContractSerializer objDCSerializer = null;
            MemoryStream ms = null;
            XmlDocument xmlDoc = null;
            MemoryStream msOp = null;
            object patternObject = null;

            try
            {
                objDCSerializer = new DataContractSerializer(typeToMap);
                ms = new MemoryStream(xmlFile);

                xmlDoc = new XmlDocument();
                xmlDoc.Load(ms);

                //Close and Dispose MemoryStream object
                //handle memory leakage problem
                ms.Close();
                ms.Dispose(); 
                
                ms = null;

                xmlDoc.DocumentElement.SetAttribute("xmlns", DATACONTRACTSERIALISER_NAMESPACE_URI);

                msOp = new MemoryStream();

                xmlDoc.Save(msOp);

                msOp.Seek(0, SeekOrigin.Begin);

                xmlDoc = null;

                patternObject = objDCSerializer.ReadObject(msOp);
                //Close and Dispose MemoryStream object
                
                msOp.Close();
                msOp.Dispose();
                msOp = null;
                
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                xmlFile = null;
                xmlDoc = null;
                ms = null;
                msOp = null;
                objDCSerializer = null;
            }
            return patternObject;
        }
        #endregion
    }
}
